// Direct3D-Hook.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "apihijack.h"
#include "Direct3D-Hook.h"
#include "MyDirect3D9.h"
#include "MyD3DXFont.h"
//#include "ModuleInfoManager.h"
#include "DialogueManager.h"

#ifdef _MANAGED
#pragma managed(push, off)
#endif

HINSTANCE hDLL;
CDialogueManager g_DialogueManager;

// Function pointer types.
typedef IDirect3D9* (WINAPI *Direct3DCreate9_t)(UINT sdk_version);

typedef HRESULT (WINAPI* D3DXCreateFontW_t)(
				  LPDIRECT3DDEVICE9       pDevice,  
				  INT                     Height,
				  UINT                    Width,
				  UINT                    Weight,
				  UINT                    MipLevels,
				  BOOL                    Italic,
				  DWORD                   CharSet,
				  DWORD                   OutputPrecision,
				  DWORD                   Quality,
				  DWORD                   PitchAndFamily,
				  LPCWSTR                 pFaceName,
				  LPD3DXFONT*             ppFont);

// Function prototypes.
IDirect3D9* WINAPI MyDirect3DCreate9(UINT sdk_version);
// Hook function.
HRESULT WINAPI 
MyD3DXCreateFontW(
				  LPDIRECT3DDEVICE9       pDevice,  
				  INT                     Height,
				  UINT                    Width,
				  UINT                    Weight,
				  UINT                    MipLevels,
				  BOOL                    Italic,
				  DWORD                   CharSet,
				  DWORD                   OutputPrecision,
				  DWORD                   Quality,
				  DWORD                   PitchAndFamily,
				  LPCWSTR                 pFaceName,
				  LPD3DXFONT*             ppFont);

// Hook structure.
enum
{
	D3DFN_Direct3DCreate9 = 0
};

enum
{
	D3DXFN_D3DXCreateFontW = 0
};

SDLLHook D3DHook = 
{
	"D3D9.DLL",
	false, NULL,		// Default hook disabled, NULL function pointer.
	{
		{ "Direct3DCreate9", MyDirect3DCreate9},
		{ NULL, NULL }
	}
};

SDLLHook D3DXFontHook = 
{
	"d3dx9_33.dll",
	false, NULL,		// Default hook disabled, NULL function pointer.
	{
		{ "D3DXCreateFontW", MyD3DXCreateFontW},
		{ NULL, NULL }
	}
};

// Hook function.
HRESULT WINAPI 
MyD3DXCreateFontW(
				LPDIRECT3DDEVICE9       pDevice,  
				INT                     Height,
				UINT                    Width,
				UINT                    Weight,
				UINT                    MipLevels,
				BOOL                    Italic,
				DWORD                   CharSet,
				DWORD                   OutputPrecision,
				DWORD                   Quality,
				DWORD                   PitchAndFamily,
				LPCWSTR                 pFaceName,
				LPD3DXFONT*             ppFont)
{
	// Let the world know we're working.
	static int FontCreateCount = 0;

	OutputDebugString( "D3DXCreateFontW called.\n" );

	D3DXCreateFontW_t old_func = (D3DXCreateFontW_t) D3DXFontHook.Functions[D3DXFN_D3DXCreateFontW].OrigFn;
	HRESULT Result = old_func(pDevice, Height, Width, Weight, MipLevels, Italic, CharSet, OutputPrecision, Quality, PitchAndFamily, pFaceName, ppFont);

	MyD3DX9Font* pMyD3DX9Font = new MyD3DX9Font();
	pMyD3DX9Font->SetD3DXFont(*ppFont);
	*ppFont = pMyD3DX9Font;

	FontCreateCount++;	

	return 0;
}

IDirect3D9* WINAPI MyDirect3DCreate9(UINT sdk_version)
{
	// Let the world know we're working.		
	OutputDebugString( "Direct3D-Hook: MyDirect3DCreate9 called.\n" );

	Direct3DCreate9_t old_func = (Direct3DCreate9_t) D3DHook.Functions[D3DFN_Direct3DCreate9].OrigFn;
	IDirect3D9* d3d = old_func(sdk_version);
	
	return d3d? new MyDirect3D9(d3d) : 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
					   DWORD  ul_reason_for_call,
					   LPVOID lpReserved
					 )
{
	if(ul_reason_for_call == DLL_PROCESS_ATTACH)  // When initializing....
	{
		hDLL = hModule;
		// We don't need thread notifications for what we're doing.  Thus, get
		// rid of them, thereby eliminating some of the overhead of this DLL
		DisableThreadLibraryCalls( hModule );

		//HookAPICalls(&D3DHook);

		g_DialogueManager.LoadDialogue("NancyDrew.xls");

		if(false == HookAPICallForNancyDrew(&D3DXFontHook))
		{
			MessageBeep(MB_ICONINFORMATION);
		}				
	}
	else if(ul_reason_for_call == DLL_PROCESS_DETACH)
	{
		g_DialogueManager.SaveDialogue();
	}

	return TRUE;
}